/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package timers;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.Timer;

import main.Main;

import org.apache.log4j.Logger;

import database.DBConnectionFactory;

/**
 * A class to manage the different timers the bot uses
 * 
 * 
 */
public class TimerHandler {
   private final List<Timer> armyTimers;
   private final List<Timer> alarmTimers;
   private Timer newsTimer;
   private final List<Timer> helpTimers;

   public TimerHandler() {
	  armyTimers = new LinkedList<Timer>();
	  alarmTimers = new LinkedList<Timer>();
	  newsTimer = null;
	  helpTimers = new LinkedList<Timer>();
   }

   public void addAlarmTimer(final Timer timer) {
	  alarmTimers.add(timer);
   }

   public void addArmyTimer(final Timer timer) {
	  armyTimers.add(timer);
   }

   public void addHelpTimer(final Timer timer) {
	  helpTimers.add(timer);
   }

   private void clearAlarmTimers() {
	  for (final Timer t : alarmTimers) {
		 t.cancel();
	  }
	  alarmTimers.clear();
   }

   private void clearArmyTimers() {
	  for (final Timer t : armyTimers) {
		 t.cancel();
	  }
	  armyTimers.clear();
   }

   public void reloadAlarmTimers() {
	  clearAlarmTimers();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM alarm WHERE settime < ?");
		 ps.setTimestamp(1, new Timestamp(Calendar.getInstance().getTimeInMillis()));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("SELECT * FROM alarm");
		 rs = ps.executeQuery();
		 while (rs.next()) {
			String user = rs.getString("mainnick");
			Long delay = Math.max(rs.getTimestamp("settime").getTime() - Calendar.getInstance().getTimeInMillis(), 0);
			String message = rs.getString("message");
			alarmTimers.add(new AlarmTimer(user, delay, message));
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			try {
			   rs.close();
			} catch (final Exception e) {
			   Logger.getLogger("Error").error("", e);
			}
			try {
			   ps.close();
			} catch (final Exception e) {
			   Logger.getLogger("Error").error("", e);
			}
		 } catch (final Exception e) {
			Logger.getLogger("Error").error("", e);
		 }
	  }
   }

   public void reloadArmyTimers() {
	  clearArmyTimers();
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("DELETE FROM army WHERE armyhome < ?");
		 ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection().prepareStatement("SELECT * FROM army");
		 rs = ps.executeQuery();

		 while (rs.next()) {
			String user = rs.getString("mainnick");
			Integer army = rs.getInt("armyno");
			Long delay = Math.max(rs.getTimestamp("armyhome").getTime() - System.currentTimeMillis(), 0);
			armyTimers.add(new ArmyTimer(user, army, delay));
		 }

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory.getConnectionHandler().getConnection()
			   .prepareStatement("DELETE FROM somarmy WHERE returntime < ?");
		 ps.setTimestamp(1, new Timestamp(System.currentTimeMillis()));
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = DBConnectionFactory
			   .getConnectionHandler()
			   .getConnection()
			   .prepareStatement(
					 "SELECT kdloc, province.name, somarmy.armyno, returntime FROM province, somarmy "
						   + "WHERE province.name = somarmy.name");
		 rs = ps.executeQuery();

		 while (rs.next()) {
			if (!rs.getString("kdloc").equals("(" + Main.getBotSettings().getKdLoc() + ")")) {
			   String province = "prov " + rs.getString("name");
			   Integer army = rs.getInt("armyno");
			   Long delay = Math.max(rs.getTimestamp("returntime").getTime() - Calendar.getInstance().getTimeInMillis(), 0);
			   armyTimers.add(new ArmyTimer(province, army, delay));
			}
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			try {
			   rs.close();
			} catch (final Exception e) {
			   Logger.getLogger("Error").error("", e);
			}
			try {
			   ps.close();
			} catch (final Exception e) {
			   Logger.getLogger("Error").error("", e);
			}
		 } catch (final Exception e) {
			Logger.getLogger("Error").error("", e);
		 }
	  }
   }

   public void removeAlarmTimer(final String user) {
	  for (final Timer timer : alarmTimers) {
		 if (((AlarmTimer) timer).getUser().equals(user)) {
			timer.cancel();
			alarmTimers.remove(timer);
			break;
		 }
	  }
   }

   public void removeArmyTimer(final String user, final int army) {
	  for (final Timer timer : armyTimers) {
		 if (((ArmyTimer) timer).getUser().equals(user) && ((ArmyTimer) timer).getArmy().equals(army)) {
			timer.cancel();
			armyTimers.remove(timer);
			break;
		 }
	  }
   }

   public void removeHelpTimer(final String user) {
	  for (final Timer timer : helpTimers) {
		 if (((HelpTimer) timer).getUser().equals(user)) {
			timer.cancel();
			helpTimers.remove(timer);
			break;
		 }
	  }
   }

   public void removeNewsTimer() {
	  if (newsTimer != null) {
		 newsTimer.cancel();
	  }
	  newsTimer = null;
   }

   public void setNewsTimer(final Timer timer) {
	  if (newsTimer != null) {
		 newsTimer.cancel();
	  }
	  newsTimer = timer;
   }
}
